package main

import (
	"log"
	"sync"
	"time"
)

type followerItem struct {
	ip         string
	updateTime int64

	cpuTotal     int32
	cpuMax       int32
	cpuUsing     int32
	cpuWait      int32
	storageTotal int32
	storageUsing int32
	time         int64

	task []*Task
}

type Record struct {
	mu           sync.Mutex
	pool         sync.Pool
	followerMap  map[string]*followerItem
	registerChan chan RegisterBody
}

func NewRecord(registerChan chan RegisterBody) *Record {
	return &Record{
		mu: sync.Mutex{},
		pool: sync.Pool{
			New: func() any {
				return new(followerItem)
			},
		},
		followerMap:  map[string]*followerItem{},
		registerChan: registerChan,
	}
}

func (r *Record) GC() {
	timer := time.NewTimer(5 * time.Second)

	for {
		<-timer.C

		r.mu.Lock()
		for _, item := range r.followerMap {
			setTime := time.Unix(item.updateTime, 0)
			if time.Since(setTime) > time.Duration(10*time.Second) {
				log.Printf("Delete follower: %v\n", item.ip)
				delete(r.followerMap, item.ip)

				item.ip = ""
				item.time = 0
				r.pool.Put(item)
			}
		}
		r.mu.Unlock()

		timer.Reset(5 * time.Second)
	}
}

func (r *Record) Register() {
	for {
		item := <-r.registerChan

		r.mu.Lock()
		if _, ok := r.followerMap[item.IP]; !ok {
			follower := r.pool.Get().(*followerItem)
			follower.ip = item.IP
			follower.updateTime = time.Now().Unix()

			follower.cpuTotal = item.CPUTotal
			follower.cpuMax = item.CPUMax
			follower.cpuUsing = item.CPUUsing
			follower.cpuWait = item.CPUWait
			follower.storageTotal = item.StorageTotal
			follower.storageUsing = item.StorageUsing
			follower.time = item.Time
			follower.task = item.Task

			r.followerMap[item.IP] = follower
			log.Printf("Register follower: %v and get %v tasks\n", follower.ip, len(item.Task))
		} else {
			follower := r.followerMap[item.IP]
			follower.updateTime = time.Now().Unix()

			follower.cpuTotal = item.CPUTotal
			follower.cpuMax = item.CPUMax
			follower.cpuUsing = item.CPUUsing
			follower.cpuWait = item.CPUWait
			follower.storageTotal = item.StorageTotal
			follower.storageUsing = item.StorageUsing
			follower.time = item.Time
			follower.task = append(follower.task, item.Task...)

			log.Printf("Update follower: %v and get %v tasks\n", follower.ip, len(item.Task))
		}
		r.mu.Unlock()
	}
}
